﻿using System;
using System.IO;
using System.Threading;
using UtilZ.Dotnet.Ex.Communication.Base;
using UtilZ.Dotnet.Ex.Model;

namespace UtilZ.Dotnet.Ex.Communication.Net.DataTransfer.Base
{
    /// <summary>
    /// 传输数据项
    /// </summary>
    public class TransferDataItem : IDisposable
    {
        private static int _sidIndex = 0;

        private int _SID;
        /// <summary>
        /// 资源标识
        /// </summary>
        public int SID
        {
            get { return this._SID; }
        }


        private TransferDataType _transferDataType = TransferDataType.BufferData;
        /// <summary>
        /// 获取传输数据类型
        /// </summary>
        public TransferDataType TransferDataType
        {
            get { return this._transferDataType; }
        }


        private byte[] _transferDataBuffer = null;
        private Stream _transferDataBufferStream = null;
        private BinaryWriter _transferDataBufferWriter = null;
        private BufferData _transferDataBufferData = null;


        /// <summary>
        /// 获取传输数据buffer
        /// </summary>
        public BufferData TransferDataBufferData
        {
            get
            {
                return this._transferDataBufferData;
            }
        }


        private BufferData _bufferData = null;
        /// <summary>
        /// 用于发送的数据Buffer
        /// </summary>
        public BufferData BufferData
        {
            get
            {
                return this._bufferData;
            }
        }

        private readonly DataSpan<byte> _dataSpan = new DataSpan<byte>();
        /// <summary>
        /// 获取byte[]数据buffer
        /// </summary>
        public DataSpan<byte> DataSpan
        {
            get { return this._dataSpan; }
        }


        private ITransferDataOptions _options;
        /// <summary>
        /// 获取发送选项
        /// </summary>
        public ITransferDataOptions SendOptions
        {
            get { return this._options; }
        }



        private IDataTransfer _dataTransfer = null;
        /// <summary>
        /// 获取或设置数据传输项所属传输对象
        /// </summary>
        public IDataTransfer DataTransfer
        {
            get { return this._dataTransfer; }
            set { this._dataTransfer = value; }
        }



        private readonly AutoResetEvent _eventWaitHandle;


        /// <summary>
        /// 构造函数
        /// </summary>
        public TransferDataItem()
        {
            this._eventWaitHandle = new AutoResetEvent(false);
        }




        private void UpdateSID()
        {
            this._SID = Interlocked.Increment(ref _sidIndex);
        }




        /// <summary>
        /// 将要发送的数据写到当前项中
        /// </summary>
        /// <param name="buffer">发送的数据</param>
        /// <param name="startIndex">发送数据起始位置</param>
        /// <param name="count">发送数据长度</param>
        /// <param name="options">发送选项</param>
        public void Write(byte[] buffer, int startIndex, int count, ITransferDataOptions options)
        {
            this._dataSpan.Update(buffer, startIndex, count);

            this._transferDataType = TransferDataType.DataSpan;
            this._options = options;
            this.UpdateSID();
        }

        /// <summary>
        /// 将要发送的数据写到当前项中
        /// </summary>
        /// <param name="bufferData">发送的数据</param>
        /// <param name="options">发送选项</param>
        public void Write(BufferData bufferData, ITransferDataOptions options)
        {
            this._bufferData = bufferData;

            this._transferDataType = TransferDataType.BufferData;
            this._options = options;
            this.UpdateSID();
        }


        /// <summary>
        /// 将要发送的数据写到当前项中
        /// </summary>
        /// <param name="data">要发送的数据对象</param>
        /// <param name="options">发送选项</param>
        public void Write(TransferDataAbs data, ITransferDataOptions options)
        {
            long length = data.GetBufferLength();
            if (this._transferDataBuffer == null || _transferDataBuffer.Length < length)
            {
                this._transferDataBuffer = new byte[length];
                if (this._transferDataBufferStream != null)
                {
                    this._transferDataBufferStream.Dispose();
                    this._transferDataBufferWriter.Dispose();
                }
                this._transferDataBufferStream = new MemoryStream(this._transferDataBuffer);
                this._transferDataBufferWriter = new BinaryWriter(this._transferDataBufferStream);
                this._transferDataBufferData = new BufferData(this._transferDataBuffer);
            }

            this._transferDataBufferWriter.BaseStream.Position = 0L;
            this._transferDataBufferData.Update(0, length);
            data.ToBufferData(this._transferDataBufferData, this._transferDataBufferWriter);

            this._transferDataType = TransferDataType.TransferData;
            this._options = options;
            this.UpdateSID();
        }




        /// <summary>
        /// 获取要发送的数据长度
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public long GetDataLength()
        {
            switch (this._transferDataType)
            {
                case TransferDataType.BufferData:
                    if (this._bufferData.DataType == BufferDataType.File)
                    {
                        using (var fs = new FileStream(this._bufferData.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            this._bufferData.UpdateFileBufferLength(fs.Length);
                        }
                    }
                    return this._bufferData.LongLength;
                case TransferDataType.TransferData:
                    return this._transferDataBufferData.LongLength;
                case TransferDataType.DataSpan:
                    return this._dataSpan.Length;
                default:
                    throw new NotImplementedException(this._transferDataType.ToString());
            }
        }

        /// <summary>
        /// 获取资源数据类型
        /// </summary>
        /// <returns>资源数据类型</returns>
        public byte GetSIDType()
        {
            if (this._transferDataType == TransferDataType.BufferData && this._bufferData.DataType == BufferDataType.File)
            {
                return DataTransferDataTypeConstant.FILE;
            }
            else
            {
                return DataTransferDataTypeConstant.MEMORY;
            }
        }

        /// <summary>
        /// 获取携带的数据
        /// </summary>
        /// <returns>携带的数据</returns>
        /// <exception cref="InvalidOperationException"></exception>
        /// <exception cref="NotImplementedException"></exception>
        public DataSpan<byte> GetData()
        {
            switch (this._transferDataType)
            {
                case TransferDataType.BufferData:
                    throw new InvalidOperationException();
                case TransferDataType.TransferData:
                    return new DataSpan<byte>(this._transferDataBufferData.Bytes, this._transferDataBufferData.Offset, this._transferDataBufferData.Length);
                case TransferDataType.DataSpan:
                    return this._dataSpan;
                default:
                    throw new NotImplementedException(this._transferDataType.ToString());
            }
        }




        /// <summary>
        /// 等待发送完成
        /// </summary>
        public void WaitCompleted()
        {
            this._eventWaitHandle.WaitOne();
        }

        /// <summary>
        /// 等待发送完成.收到消息返回true,超时返回false
        /// </summary>
        /// <param name="millisecondsTimeout">超时时长</param>
        /// <returns>等待结果,收到消息返回true,超时返回false</returns>
        public bool WaitCompleted(int millisecondsTimeout)
        {
            return this._eventWaitHandle.WaitOne(millisecondsTimeout);
        }

        /// <summary>
        /// 发送完成通知
        /// </summary>
        public void SendCompleted()
        {
            this._eventWaitHandle.Set();
        }


        private bool _timeout = false;
        /// <summary>
        /// 发送超时标识[]true:发送超时;false:成功
        /// </summary>
        public bool Timeout
        {
            get
            {
                return this._timeout;
            }
        }

        /// <summary>
        /// 重置发送状态
        /// </summary>
        public void Reset()
        {
            this._timeout = false;
        }

        /// <summary>
        /// 发送超时
        /// </summary>
        public void SendTimeout()
        {
            this._eventWaitHandle.Set();
            this._timeout = true;
        }


        /// <summary>
        /// 发送类型
        /// </summary>
        public ThreadMode SendType { get; set; }

        /// <summary>
        /// 是否取消
        /// </summary>
        public bool IsCancell { get; set; }

        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            if (this._transferDataBufferStream != null)
            {
                this._transferDataBufferStream.Dispose();
                this._transferDataBufferWriter.Dispose();
            }

            this._eventWaitHandle.Dispose();
        }


    }

    /// <summary>
    /// 传输类型
    /// </summary>
    public enum TransferDataType
    {
        /// <summary>
        /// 传输数据项
        /// </summary>
        TransferData,

        /// <summary>
        /// BufferData
        /// </summary>
        BufferData,

        /// <summary>
        /// byte[]数据片
        /// </summary>
        DataSpan
    }
}
